package edu.codink.common.base;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Service;


/**
 * 
 * @author zhangliang
 *
 */
@SuppressWarnings("unchecked")
@Service
public class BasicHbmDao extends HibernateDaoSupport {
	
	@Autowired
	public void setSessionFactoryBase(SessionFactory sessionFactory){  
	   super.setSessionFactory(sessionFactory);
	} 
	
    public <T extends Serializable> boolean save(T obj)
    {
    	this.getHibernateTemplate().save(obj);
    	this.flush();
        return true;
    }
	public <T extends Serializable> boolean saveOrUpdate(T obj)
	{
    	this.getHibernateTemplate().saveOrUpdate(obj);
		this.flush();
		return true;
    }
	
	public <T extends Serializable> T getSave(T obj)	
	{
		return (T) this.getHibernateTemplate().save(obj);
	}
    

    public <T extends Serializable> boolean update(T obj) 
    {
    	this.getHibernateTemplate().update(obj);
		this.flush();
		return true;
    }

    /**
	 * 加载单个对象
	 * @param <T>
	 * @param clazz
	 * @param id
	 * @return
	 */
	protected <T extends Serializable> T find(Class<T> clazz,final Serializable id)
	{
		return this.getHibernateTemplate().load(clazz, id);
	}
    /**
	 * 删除对象信息
	 * @param obj
	 */
	public <T extends Serializable> void remove(T obj)
	{
		this.getHibernateTemplate().delete(obj);
		this.flush();
	}
	/**
	 * 根据指定的CLASS及主键ID，删除对象的基本信息
	 * @param clazz
	 * @param id
	 */
	public <T extends Serializable> void remove(Class<T> clazz,final Serializable id)
	{
		this.remove(this.find(clazz, id));
		this.flush();
	}
    
	public <T extends Serializable> boolean saveOrUpdateAll(List<T> list) {
		this.getHibernateTemplate().saveOrUpdateAll(list);
		this.flush();
		return true;
	}
	
   
    public boolean updateByHqlQuery(final String queryString, final Object[] params) {
    	this.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) {
				Query query = session.createQuery(queryString);
				if (params != null) {
					int length = params.length;
					for (int i = 0; i < length; i++) {
						query.setParameter(i, params[i]);
					}
				}
				query.executeUpdate();
				return true;
			}
		});
    	this.flush();
    	return true;
    }
    
  
	public void updateByHqlQuery(final String queryStr)
	{
		this.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) {
				Query query = session.createQuery(queryStr);
				query.executeUpdate();
				return null;
			}
		});
		this.flush();
	}

    public <T extends Serializable> boolean del(T obj) {
    	this.getHibernateTemplate().delete(obj);
		this.flush();
		return true;
    }
    
	
	public <T extends Serializable> boolean delAll(List<T> list) {
		this.getHibernateTemplate().deleteAll(list);
		this.flush();
		return true;
	}
	
  
    public <T extends Serializable> void delAll(final Class<T> clazz) {
    	this.getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session) {
						Query query = session.createQuery("delete "
								+ clazz.getName());
						return new Integer(query.executeUpdate());
					}
				});
    	
    	this.flush();
        
    }

   
	public <T extends Serializable> boolean delById(Class<T> clazz, Serializable id) {
		this.getHibernateTemplate().delete(get(clazz, id));
		this.flush();
		return true;
    }

   
    public void delByHqlQuery(final String queryString,final Object[] parameters) {
    	this.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) {
				Query query = session.createQuery(queryString);
				if (parameters != null) {
					int length = parameters.length;
					for (int i = 0; i < length; i++) {
						query.setParameter(i, parameters[i]);
					}
				}
				return new Integer(query.executeUpdate());
			}
		});
    	
    	this.flush();
    }

  
    public <T> List<T> findAll(Class<T> clazz) {
        return this.getHibernateTemplate().loadAll(clazz);
    }

   
    /**
	 * 查询某类对象所有的数据
	 * @param <T>
	 * @param clazz
	 * @return
	 */
	public <T> List<T> findAll(Class<T> clazz,String orderBy) {
		return this.getHibernateTemplate().find("from " + clazz.getName()+(orderBy==null?null:" order by "+orderBy));
	}
    
	public <T> T findOne(final String hql, Class<T> entityClass)
	{
		List<T> list =  this.getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				Query query=arg0.createQuery(hql);
				query.setFirstResult(0);
				query.setMaxResults(1);
				List<T> list = query.list();
				return list;
			}
		});
		
		if (list.isEmpty()) {
			return null;
		} else {
			return list.get(0);
		}
	}
	
	public <T> T findOne(final String hql, final Object[] params, Class<T> entityClass)
	{
		List<T> list =  this.getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				Query query=arg0.createQuery(hql);
				if(params!=null){
					int length=params.length;
					for(int i=0;i<length;i++){
						query.setParameter(i, params[i]);
					}
				}
				query.setFirstResult(0);
				query.setMaxResults(1);
				List<T> list = query.list();
				return list;
			}
		});
		
		if (list.isEmpty()) {
			return null;
		} else {
			return list.get(0);
		}
	}
   
    public <T> T load(Class<T> clazz, Serializable id) {
    	
    	return this.getHibernateTemplate().load(clazz, (Serializable) id);
    }

    public <T> T get(Class<T> clazz, Serializable id) {
    	return (T) this.getHibernateTemplate().get(clazz, id);
    }
    

    public <T> List<T> findByNamedQuery(String queryName) {
        return this.getHibernateTemplate().findByNamedQuery(queryName);  
    }

    public <T> List<T> findByNamedQuery(String queryName, Object[] params) {
    	return this.getHibernateTemplate().find(queryName, params);
    }

  
    public List findHql(String hql) {
    	return this.getHibernateTemplate().find(hql);
    }
    
    public <T> List<T> findHql(String hql, Class<T> entityClass) {
    	return this.getHibernateTemplate().find(hql);
    }
   
	public void flush()
	{
		this.getHibernateTemplate().flush();
		this.getHibernateTemplate().clear();
	}

    public <T> List<T> find(String queryString, final Object[] params) {
    	return this.getHibernateTemplate().find(queryString, params);
    }
	
	public <T> T merge(T t) 
	{
		this.getHibernateTemplate().merge(t);
		this.flush();
		return t;
	}
	
	/**
	 * 通过HQL的方式进行数据查询，并进行分页
	 * @param hql HQL语句
	 * @param page 分布对象
	 * @param params 参数对象
	 * @return
	 */
	public <T> List<T> selectByPageHql(final String hql,final Page page,final Object... params){
		return this.getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				Query query=arg0.createQuery(hql);
				if(params!=null){
					int length=params.length;
					for(int i=0;i<length;i++){
						query.setParameter(i, params[i]);
					}
				}
				if(page!=null){
					query.setFirstResult(page.getStartRow());
					query.setMaxResults(page.getPageSize());
				}
				List<T> list = query.list();
				return list;
			}
		});
		
	}
	
	/**
	 * 通过HQL的方式进行数据查询，并进行分页
	 * @param hql HQL语句
	 * @param page 分布对象
	 * @param params 参数对象
	 * @return
	 */
	public <T> List<T> selectByStartLimitPageHql(final String hql,final Page page,final Object... params){
		return this.getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				Query query=arg0.createQuery(hql);
				if(params!=null){
					int length=params.length;
					for(int i=0;i<length;i++){
						query.setParameter(i, params[i]);
					}
				}
				if(page!=null){
					query.setFirstResult(page.getStart());
					query.setMaxResults(page.getLimit());
				}
				List<T> list = query.list();
				return list;
			}
		});
		
	}
	
	/**
	 * 通过HQL的方式查询数量
	 * @param sql
	 * @param params
	 * @return
	 */
	public long hqlCount(String hql,Object... params){
		return (Long)this.getHibernateTemplate().find(hql, params).get(0);
	}

	/**
	 * 通过HQL的方式更新数据
	 * @param hql
	 * @param params
	 * @return
	 */
	public int updateOrDelHql(final String hql,final Object... params){
		Integer result = (Integer)this.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
			throws HibernateException, SQLException {
				Query query=session.createQuery(hql);
				if(params!=null){
					int length=params.length;
					for(int i=0;i<length;i++){
						query.setParameter(i, params[i]);
					}
				}
				return query.executeUpdate();
			}
			
		});
		return result;
	}
	
	public <T> List<T> findSQL(final String sql)
	{
		return this.getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session s) throws HibernateException,
					SQLException {
				Query query = s.createSQLQuery(sql);
				List<T> list = query.list();
				return list;
			}
		});
	}
	
	public <T> List<T> findSQL(final String sql , final Class<T> entityClass)
	{
		return this.getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session s) throws HibernateException,
					SQLException {
				SQLQuery query = s.createSQLQuery(sql).addEntity(entityClass);
				List<T> list = query.list();
				return list;
			}
		});
	}
	/**
	 * 通过HQL的方式进行数据查询
	 * @param hql HQL语句
	 * @param clazz 查询结果对应的CLASS
	 * @param params 参数对象
	 * @return
	 */
	public <T> List<T> selectAllHql(String hql,Object... params){
		return selectByPageHql(hql, null, params);
	}
	/**
	 * 通过HQL的方式进行数据查询，并进行分页
	 * @param hql HQL语句
	 * @param clazz 查询结果对应的CLASS
	 * @param page 分布对象
	 * @param params 参数对象
	 * @return
	 */
	public <T> List<T> selectByPageSql(final String sql,final Page page,final Object... params){
		return this.getHibernateTemplate().executeFind(new HibernateCallback() {
			
			public Object doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				Query query=arg0.createSQLQuery(sql);
				if(params!=null){
					int length=params.length;
					for(int i=0;i<length;i++){
						query.setParameter(i, params[i]);
					}
				}
				if(page!=null){
					query.setFirstResult(page.getStartRow());
					query.setMaxResults(page.getPageSize());
				}
				List<T> list = query.list();
				return list;
			}
		});
	}
	
	/**
	 * 通过SQL的方式进行数据查询，并进行分页
	 * @param hql HQL语句
	 * @param clazz 查询结果对应的CLASS
	 * @param page 分布对象
	 * @param params 参数对象
	 * @return
	 */
	public <T> List<T> selectByStartLimitPageSql(final String sql,final Page page,final Object... params){
		return this.getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				Query query=arg0.createSQLQuery(sql);
				if(params!=null){
					int length=params.length;
					for(int i=0;i<length;i++){
						query.setParameter(i, params[i]);
					}
				}
				if(page!=null){
					query.setFirstResult(page.getStart());
					query.setMaxResults(page.getLimit());
				}
				List<T> list = query.list();
				return list;
			}
		});
	}
	
	/**
	 * 通过SQL的方式进行数据查询
	 * @param hql HQL语句
	 * @param clazz 查询结果对应的CLASS
	 * @param params 参数对象
	 * @return
	 */
	public  <T> List<T> selectAllSql(String sql,Object... params){
		return selectByPageSql(sql, null, params);
	}
	
	/**
	 * 获得Query
	 * @param hql
	 * @return
	 * zhangliang
	 * 2011-8-1
	 */
	public Query createHqlQuery(String hql)
	{
		Query query = this.getSession().createQuery(hql);
		return query;
	}
	
	
	/**
	 * 通过SQL的方式更新数据
	 * @param sql
	 * @param params
	 * @return
	 */
	public int updateOrDelBySql(final String sql,final Object... params){
		int result=(Integer)this.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				Query query=arg0.createSQLQuery(sql);
				if(params!=null){
					int length = params.length;
					for(int i=0;i<length;i++){
						Object obj = params[i];
						
						if(obj instanceof Integer){}
						query.setParameter(i, obj,StandardBasicTypes.getHibernateType(obj));
					}
				}
				return query.executeUpdate();
			}
		});
		this.flush();
		return result;
	}
	
	/**
	 * 通过SQL查询单个对象
	 * @param <T>
	 * @param sql
	 * @param params
	 * @return
	 */
	public Object selectObjBySql(String sql,Object... params){
		List list = selectAllBySql(sql, params);
		if(list == null|| list.size() == 0){
			return null;
		}else{
			return list.get(0);
		}
	}
	
	/**
	 * 通过SQL的方式进行数据查询
	 * @param hql HQL语句
	 * @param clazz 查询结果对应的CLASS
	 * @param params 参数对象
	 * @return
	 */
	public <T> List<T> selectAllBySql(String sql,Object... params){
		return selectByPageSql(sql, null, params);
	}
	
	/**
	 * 通过SQL的方式更新数据
	 * @param sql
	 * @param params
	 * @return
	 */
	public int updateOrDelBySql(final String sql,final List<Object> params){
		int result=(Integer)this.getHibernateTemplate().execute(new HibernateCallback() {
			
			public Object doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				Query query=arg0.createSQLQuery(sql);
				if(params!=null){
					int length=params.size();
					for(int i=0;i<length;i++){
						Object obj = params.get(i);
						//if(obj == null){obj = "";}
						query.setParameter(i, params.get(i),StandardBasicTypes.getHibernateType(obj));
					}
				}
				return query.executeUpdate();
			}
		});
		this.flush();
		return result;
	}
}